home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr44 / frasrc19.zip / GIFVIEW.C < prev    next >
C/C++ Source or Header  |  1994-11-28  |  9KB  |  350 lines

  1. /*
  2.  *
  3.  * This GIF decoder is designed for use with the FRACTINT program.
  4.  * This decoder code lacks full generality in the following respects:
  5.  * supports non-interlaced GIF files only, and calmly ignores any
  6.  * local color maps and non-Fractint-specific extension blocks.
  7.  *
  8.  * GIF and 'Graphics Interchange Format' are trademarks (tm) of
  9.  * Compuserve, Incorporated, an H&R Block Company.
  10.  *
  11.  *                                            Tim Wegner
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #ifndef XFRACT
  18. #include <dos.h>
  19. #endif
  20. #include "fractint.h"
  21. #include "prototyp.h"
  22.  
  23. static void close_file(void);
  24.  
  25. #define MAXCOLORS    256
  26.  
  27. static FILE *fpin = NULL;    /* FILE pointer       */
  28. unsigned int height;
  29. unsigned numcolors;
  30. static int out_line_dither(BYTE *, int);
  31. static int out_line_migs(BYTE *, int);
  32. int bad_code_count = 0;     /* needed by decoder module */
  33. unsigned int gifview_image_top;    /* (for migs) */
  34. unsigned int gifview_image_left;    /* (for migs) */
  35. unsigned int gifview_image_twidth;    /* (for migs) */
  36.  
  37. int get_byte()
  38. {
  39.    return (getc(fpin)); /* EOF is -1, as desired */
  40. }
  41.  
  42. int get_bytes(BYTE *where,int how_many)
  43. {
  44.    return (fread((char *)where,1,how_many,fpin)); /* EOF is -1, as desired */
  45. }
  46.  
  47. #ifdef XFRACT
  48. BYTE decoderline[MAXPIXELS+1]; /* write-line routines use this */
  49. #endif
  50.  
  51. static char far *ditherbuf = NULL;
  52.  
  53. /* Main entry decoder */
  54.  
  55. int gifview()
  56. {
  57.    BYTE buffer[16];
  58.    unsigned top, left, width, finished;
  59.    char temp1[81];
  60.  
  61.    int status;
  62.    int i, j, k, planes;
  63.  
  64.    status = 0;
  65.  
  66.    /* initialize the row count for write-lines */
  67.    rowcount = 0;
  68.  
  69.    /* zero out the full write-line */
  70.    for (width = 0; width < MAXPIXELS+1; width++) decoderline[width] = 0;
  71.  
  72.    /* Open the file */
  73.    if(outln == outline_stereo)
  74.       strcpy(temp1,stereomapname);
  75.    else
  76.       strcpy(temp1,readname);
  77.    if (strchr(temp1,'.') == NULL) {
  78.       strcat(temp1,DEFAULTFRACTALTYPE);
  79.       if ((fpin = fopen(temp1,"rb")) != NULL) {
  80.      fclose(fpin);
  81.      }
  82.       else {
  83.          if(outln == outline_stereo)
  84.             strcpy(temp1,stereomapname);
  85.          else
  86.             strcpy(temp1,readname);
  87.      strcat(temp1,ALTERNATEFRACTALTYPE);
  88.      }
  89.       }
  90.    if ((fpin = fopen(temp1, "rb")) == NULL) {
  91.       return (-1);
  92.       }
  93.  
  94.    /* Get the screen description */
  95.    for (i = 0; i < 13; i++)
  96.    {
  97.       int tmp;
  98.  
  99.       buffer[i] = (BYTE)(tmp = get_byte());
  100.       if (tmp < 0)
  101.       {
  102.      close_file();
  103.      return(-1);
  104.       }
  105.    }
  106.  
  107.    if(strncmp((char *)buffer,"GIF87a",3) ||             /* use updated GIF specs */
  108.       buffer[3] < '0' || buffer[3] > '9' ||
  109.       buffer[4] < '0' || buffer[4] > '9' ||
  110.       buffer[5] < 'A' || buffer[5] > 'z' )
  111.    {
  112.       close_file();
  113.       return(-1);
  114.    }
  115.  
  116.    width  = buffer[6] | (buffer[7] << 8);
  117.    height = buffer[8] | (buffer[9] << 8);
  118.    planes = (buffer[10] & 0x0F) + 1;
  119.    gifview_image_twidth = width;
  120.  
  121.    if((buffer[10] & 0x80)==0)     /* color map (better be!) */
  122.    {
  123.       close_file();
  124.       return(-1);
  125.    }
  126.    numcolors = 1 << planes;
  127.  
  128.    if (dither_flag && numcolors>2 && colors==2 && outln==out_line) {
  129.      outln = out_line_dither;
  130.    }
  131.  
  132.    for (i = 0; i < (int)numcolors; i++)
  133.    {
  134.       for (j = 0; j < 3; j++) {
  135.      if ((k = get_byte()) < 0)
  136.      {
  137.         close_file();
  138.         return(-1);
  139.      }
  140.      /*
  141.      {
  142.         char msg[80];
  143.         sprintf(msg,"initbatch %d colorstate %d mapset %d",initbatch, colorstate, mapset);
  144.              stopmsg(0,msg);
  145.      }
  146.      */
  147.      if((!display3d || (glassestype != 1 && glassestype != 2)) 
  148.                    && !dontreadcolor)
  149.         dacbox[i][j] = (BYTE)(k >> 2); 
  150.       }
  151.    }
  152.    colorstate = 1; /* colors aren't default and not a known .map file */
  153.    
  154.    /* don't read if glasses */
  155.    if (display3d && mapset && glassestype!=1 && glassestype != 2)
  156.    {
  157.        ValidateLuts(MAP_name);    /* read the palette file */
  158.        spindac(0,1); /* load it, but don't spin */
  159.    }
  160.    if (dacbox[0][0] != 255)
  161.       spindac(0,1);      /* update the DAC */
  162.    if (dotmode == 11){ /* disk-video */
  163.       char fname[FILE_MAX_FNAME];
  164.       char ext[FILE_MAX_EXT];
  165.       char tmpname[15];
  166.       char msg[40];
  167.        splitpath(temp1,NULL,NULL,fname,ext);
  168.        makepath(tmpname,NULL,NULL,fname,ext);
  169.        sprintf(msg,"restoring %s",tmpname);
  170.        dvid_status(1,msg);
  171.    }
  172.    dontreadcolor = 0;
  173.    
  174.    /* Now display one or more GIF objects */
  175.    finished = 0;
  176.    while (!finished)
  177.    {
  178.       switch (get_byte())
  179.       {
  180.       case ';':
  181.      /* End of the GIF dataset */
  182.  
  183.      finished = 1;
  184.      status = 0;
  185.      break;
  186.  
  187.       case '!':                               /* GIF Extension Block */
  188.      get_byte();             /* read (and ignore) the ID */
  189.      while ((i = get_byte()) > 0)     /* get the data length */
  190.         for (j = 0; j < i; j++)
  191.            get_byte();     /* flush the data */
  192.      break;
  193.       case ',':
  194.      /*
  195.       * Start of an image object. Read the image description.
  196.       */
  197.  
  198.      for (i = 0; i < 9; i++)
  199.      {
  200.             int tmp;
  201.  
  202.             buffer[i] = (BYTE)(tmp = get_byte());
  203.         if (tmp < 0)
  204.         {
  205.            status = -1;
  206.            break;
  207.         }
  208.      }
  209.      if(status < 0)
  210.      {
  211.         finished = 1;
  212.         break;
  213.      }
  214.  
  215.      left    = buffer[0] | (buffer[1] << 8);
  216.      top    = buffer[2] | (buffer[3] << 8);
  217.      width    = buffer[4] | (buffer[5] << 8);
  218.      if (pot16bit) width >>= 1;
  219.      height = buffer[6] | (buffer[7] << 8);
  220.  
  221.          /* adjustments for handling MIGs */
  222.          gifview_image_top  = top;
  223.          if (skipxdots > 0)
  224.              gifview_image_top /= (skipydots+1);
  225.          gifview_image_left = left;
  226.          if (skipydots > 0)
  227.              gifview_image_left /= (skipxdots+1);
  228.          if (outln==out_line &&
  229.              (width != gifview_image_twidth || top != 0)) {
  230.               /* we're using normal decoding and we have a MIG */
  231.          outln = out_line_migs;
  232.              }
  233.  
  234.          /* Skip local color palette */
  235.          if((buffer[8] & 0x80)==0x80) {      /* local map? */
  236.              int numcolors;    /* make this local */
  237.              planes = (buffer[8] & 0x0F) + 1;
  238.              numcolors = 1 << planes;
  239.              /* skip local map */
  240.              for (i = 0; i < numcolors; i++) {
  241.                 for (j = 0; j < 3; j++) {
  242.                    if ((k = get_byte()) < 0) {
  243.                       close_file();
  244.                       return(-1);
  245.                       }
  246.                    }
  247.                 }
  248.              }
  249.  
  250.          /* initialize the row count for write-lines */
  251.          rowcount = 0;
  252.  
  253.          /* zero out the full write-line */
  254.          {
  255.          int i;
  256.          for (i = 0; i < MAXPIXELS+1; i++) decoderline[i] = 0;
  257.          }
  258.  
  259.      if (calc_status == 1) /* should never be so, but make sure */
  260.         calc_status = 0;
  261.      busy = 1;    /* for slideshow CALCWAIT */
  262.      status = timer(1,NULL,width); /* call decoder(width) via timer */
  263.      busy = 0;    /* for slideshow CALCWAIT */
  264.      if (calc_status == 1) /* e.g., set by line3d */
  265.      {
  266.         calctime = timer_interval; /* note how long it took */
  267.         if (keypressed() != 0) {
  268.            calc_status = 3; /* interrupted, not resumable */
  269.                finished = 1;
  270.            }
  271.         else
  272.            calc_status = 4; /* complete */
  273.      }
  274.          /* Hey! the decoder doesn't read the last (0-length) block!! */
  275.          if (get_byte() != 0) {
  276.              status = -1;
  277.              finished = 1;
  278.              }
  279.      break;
  280.       default:
  281.      status = -1;
  282.      finished = 1;
  283.      break;
  284.       }
  285.    }
  286.    close_file();
  287.    if (dotmode == 11) { /* disk-video */
  288.       static FCODE o_msg[] = {"Restore completed"};
  289.       char msg[sizeof(o_msg)];
  290.       far_strcpy(msg,o_msg);
  291.       dvid_status(0,msg);
  292.       dvid_status(1,"");
  293.       }
  294.       
  295.     if (ditherbuf != NULL) { /* we're done, free dither memory */
  296.         farmemfree(ditherbuf);
  297.         ditherbuf = NULL;
  298.     }
  299.  
  300.    return(status);
  301. }
  302.  
  303. static void close_file()
  304. {
  305.    fclose(fpin);
  306.    fpin = NULL;
  307. }
  308.  
  309. /* routine for MIGS that generates partial output lines */
  310.  
  311. static int out_line_migs(BYTE *pixels, int linelen)
  312. {
  313. int row, startcol, stopcol;
  314.  
  315. row = gifview_image_top + rowcount;
  316. startcol = gifview_image_left;
  317. stopcol = startcol+linelen-1;
  318. put_line(row, startcol, stopcol, pixels);
  319. rowcount++;
  320.  
  321. return(0); /* Bert, what is supposed to be returned? JCO */
  322. }
  323.  
  324.  
  325. static int out_line_dither(BYTE *pixels, int linelen)
  326. {
  327.     int i,nexterr,brt,err;
  328.     if(ditherbuf == NULL)
  329.         ditherbuf = (char far *)farmemalloc(linelen+1);
  330.     far_memset( ditherbuf, 0, linelen+1); 
  331.  
  332.     nexterr = (rand15()&0x1f)-16;
  333.     for (i=0;i<linelen;i++) {
  334.     brt = (dacbox[pixels[i]][0]*5+dacbox[pixels[i]][1]*9 +
  335.         dacbox[pixels[i]][2]*2)>>4; /* brightness from 0 to 63 */
  336.     brt += nexterr;
  337.     if (brt>32) {
  338.         pixels[i] = 1;
  339.         err = brt-63;
  340.     } else {
  341.         pixels[i] = 0;
  342.         err = brt;
  343.     }
  344.     nexterr = ditherbuf[i+1]+err/3;
  345.     ditherbuf[i] = (char)(err/3);
  346.     ditherbuf[i+1] = (char)(err/3);
  347.     }
  348.     return out_line(pixels, linelen);
  349. }
  350.